﻿using System;
using System.Collections.Generic;
using System.Linq;

using Newtonsoft.Json.Linq;

namespace Utils.Cache
{

    public class AutoCacheQueryable<T> 
    {
        private readonly IQueryable<T> query;
        private readonly ICacheStrategy strategy;
        public AutoCacheQueryable(ICacheStrategy strategy, IQueryable<T> query)
        {
            this.strategy = strategy.Change(2);
            this.query = query;
        }



        public void Init<K, V>(Func<IQueryable<T>, Dictionary<K, V>> hashFunc) where K : notnull
        {
            var appendKey = StringHelper.HumpToUnderline(typeof(T).Name);
            Init(appendKey, hashFunc);
        }

        public void Init<K, V>(string appendKey, Func<IQueryable<T>, Dictionary<K, V>> hashFunc) where K : notnull
        {
            var baseKey = "auto_cache_" + appendKey;

            if (strategy != null && !strategy.HasKey(baseKey))
            {
                var hashVaues = hashFunc(query);
                if (typeof(V).Equals(typeof(string)))
                {
                    strategy.SetHash(baseKey, hashVaues.ToDictionary(a => a.Key.ToString(), a => new { Name = a.Value }));
                }
                else
                {
                    strategy.SetHash(baseKey, hashVaues.ToDictionary(a => a.Key.ToString(), a => a.Value));
                }
            }
        }

        public void Set<K, V>(string appendKey, K key, V value) where K : notnull
        {
            var baseKey = "auto_cache_" + appendKey;
            if (strategy != null)
            {
                if (typeof(V).Equals(typeof(string)))
                {
                    strategy.AddHash(baseKey, key.ToString(), new { Name = value });
                }
                else
                {
                    strategy.AddHash(baseKey, key.ToString(), value);
                }
            }
        }

        public void Set<K, V>(K key, V value)
        {
            Set(StringHelper.HumpToUnderline(typeof(T).Name), key, value);
        }

        public void Remove<K>(string appendKey, K key) where K : notnull
        {
            var baseKey = "auto_cache_" + appendKey;
            if (strategy != null)
            {
                strategy.DeleteHash(baseKey, key.ToString());
            }
        }

        public void Remove<K>(K key) where K : notnull
        {
            Remove(StringHelper.HumpToUnderline(typeof(T).Name), key);
        }

        public JObject GetObject(string key)
        {
            var appendKey = StringHelper.HumpToUnderline(typeof(T).Name);
            return GetObject(appendKey, key);
        }

        public JObject GetObject(string appendKey, string key)
        {
            var baseKey = "auto_cache_" + appendKey;
            if (strategy != null)
            {
                return strategy.GetHash<JObject>(baseKey, key.ToString());
            }
            return null;
        }

    }


    public class AutoCacheQueryable
    {

        private static ICacheStrategy Strategy;
        public static void Init(IServiceProvider serviceProvider)
        {
            Strategy = (ICacheStrategy)serviceProvider.GetService(typeof(ICacheStrategy));
            if (Strategy == null) return;
            Strategy = Strategy.Change(2);
        }

        public static bool IsLoad()
        {
            return Strategy != null;
        }

        public static JObject GetObject(string baseKey, string key)
        {
            try
            {
                return Strategy.GetHash<JObject>(baseKey, key);
            }
            catch (Exception)
            {
                return null;
            }
        }
    }
}
